package com.youlu.campus.service.kos;

import com.youlu.campus.common.utils.IdGeneratorUtils;
import com.youlu.campus.entity.*;
import com.youlu.campus.entity.commission.DistributorApply;
import com.youlu.campus.entity.commission.dto.DistributorChannelSharingCommissionOrderDTO;
import com.youlu.campus.entity.commission.dto.SharingCommissionOrderDTO;
import com.youlu.campus.entity.course.dto.GoodsOrderDTO;
import com.youlu.campus.entity.course.dto.KosActivityDTO;
import com.youlu.campus.entity.course.entity.CourseSimpleActivityEntity;
import com.youlu.campus.entity.course.entity.KosCoupons;
import com.youlu.campus.entity.course.entity.UserKosCouponsOrder;
import com.youlu.campus.entity.course.vo.KosActivityDetailVo;
import com.youlu.campus.entity.enums.CourseOrderStatusEnum;
import com.youlu.campus.entity.enums.SharingProfitOrderTypeEnum;
import com.youlu.campus.service.activity.UserParticipateActivityInfoService;
import com.youlu.campus.service.activity.WechatMiniQaService;
import com.youlu.campus.service.cache.CacheUserService;
import com.youlu.campus.service.commission.CourseOrderCommissionServiceService;
import com.youlu.campus.service.commission.DistributorChannelSharingCommissionService;
import com.youlu.campus.service.course.UserActivityService;
import com.youlu.campus.service.course.WechatPayService;
import com.youlu.campus.service.order.MerchantSharingProfitService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.sql.Date;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Objects;

/**
 * @author : [dengbo]
 * @className : UserKosService
 * @description : [用户kos活动]
 * @createTime : [2022/9/14 14:33]
 */
@Service
@Slf4j
public class UserKosService {

    @Autowired
    private WechatPayService wechatPayService;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private KosCouponsService kosCouponsService;

    @Autowired
    private UserActivityService userActivityService;

    @Autowired
    private CacheUserService cacheUserService;

    @Autowired
    private WechatMiniQaService wechatMiniQaService;

    @Autowired
    private MerchantSharingProfitService merchantSharingProfitService;

    @Autowired
    private CourseOrderCommissionServiceService courseOrderCommissionServiceService;

    @Autowired
    private DistributorChannelSharingCommissionService distributorChannelSharingCommissionService;

    @Lazy
    @Autowired
    private UserParticipateActivityInfoService userParticipateActivityInfoService;

    public KosActivityDetailVo setRedeemCodeAndStatus(KosActivityDTO dto, KosActivityDetailVo detailVo) {
        detailVo.setRedeemCode("");
        detailVo.setStatus(0);
        if (dto.getUserId() == null) {
            return detailVo;
        }
        UserKosCouponsOrder order = getPayOrderByUserIdAndAid(dto.getUserId(),dto.getActivityId());
        if (order != null) {
            detailVo.setRedeemCode(order.getRedeemCode());
            detailVo.setStatus(1);
        }
        return detailVo;
    }

    public Triple<Boolean, Object, String> createKosOrder(KosActivityDTO dto, CourseSimpleActivityEntity activityInfo) {
        UserKosCouponsOrder order = getPayOrderByUserIdAndAid(dto.getUserId(),dto.getActivityId());
        if (order != null) {
            return Triple.of(false, null, "已经购买了");
        }
        return createOrder(dto, activityInfo);
    }

    public Triple<Boolean, Object, String> createOrder(KosActivityDTO dto, CourseSimpleActivityEntity activity) {
        UserPO userPO = dto.getUserPO();
        UserKosCouponsOrder courseOrder = buildCourseOrder(dto, activity);
        // 获取商户信息
        WechatMerchantConfig merchantInfo = wechatPayService.getRandomMerchant(userPO.getAppId());
        courseOrder.setMerchantId(merchantInfo.getMerchantId());
        courseOrder.setMerchantName(merchantInfo.getMerchantName());
        // 获取支付凭证
        Triple<Boolean, Object, String> result = wechatPayService.unifiedOrder(buildGoodsOrderParam(courseOrder),
                merchantInfo, dto.getNotifyUrl());
        if (result.getLeft()) {
            // 创建新的订单
            courseOrder.setPayInfo(result.getMiddle());
            mongoTemplate.insert(courseOrder);
        }
        return result;
    }

    public UserKosCouponsOrder buildCourseOrder(KosActivityDTO dto, CourseSimpleActivityEntity activity) {
        UserPO userPO = dto.getUserPO();
        //获取支付凭证
        UserKosCouponsOrder courseOrder = new UserKosCouponsOrder();
        courseOrder.setUserId(userPO.getId());
        courseOrder.setStatus(CourseOrderStatusEnum.NOT_PAY.getValue());
        courseOrder.setPrice(activity.getKosPrice());
        courseOrder.setName(activity.getName());
        courseOrder.setActivityId(dto.getActivityId());
        String orderNo = IdGeneratorUtils.generateKosNo();
        courseOrder.setOrderNo(orderNo);
        courseOrder.setAppId(userPO.getAppId());
        courseOrder.setPlatform(userPO.getCurrentPlatform());
        courseOrder.setOpenId(userPO.getOpenId());
        courseOrder.setUnionId(userPO.getUnionId());
        courseOrder.setPhone(userPO.getMobile());
        courseOrder.setNickName(userPO.getNickName());
        courseOrder.setClientIp(dto.getClientIp());
        LocalDateTime now = LocalDateTime.now();
        courseOrder.setStartTime(now);
        courseOrder.setActivityChannelId(dto.getActivityChannelId());
        // 订单有效时间2分钟,2分钟失效
        LocalDateTime expireTime = now.plus(60 * 10, ChronoUnit.SECONDS);
        courseOrder.setExpireTime(expireTime);
        return courseOrder;
    }

    public GoodsOrderDTO buildGoodsOrderParam(UserKosCouponsOrder order) {
        GoodsOrderDTO dto = new GoodsOrderDTO();
        dto.setOrderNo(order.getOrderNo());
        dto.setClientIp(order.getClientIp());
        dto.setOpenId(order.getOpenId());
        dto.setGoodsName(order.getName());
        dto.setPrice(order.getPrice());
        dto.setUserId(order.getUserId());
        dto.setAppId(order.getAppId());
        dto.setStartTime(order.getStartTime());
        dto.setStartTime(order.getExpireTime());
        return dto;
    }

    public UserKosCouponsOrder getPayOrderByUserIdAndAid(String userId, String activityId) {
        Query courseOrderQuery = new Query(Criteria.where("userId").is(userId).and("activityId").is(activityId).and("status").is(CourseOrderStatusEnum.PAY_SUCCESS.getValue()));
        return mongoTemplate.findOne(courseOrderQuery, UserKosCouponsOrder.class);
    }

    /**
     * 处理支付回调
     *
     * @param orderNo
     * @param transactionId
     */
    public void dealOrderPayNotity(String orderNo, String transactionId) {
        UserKosCouponsOrder order = getOrderByOrderNo(orderNo);
        log.info("before deal order orderNo:{} orderStatus:{}", orderNo, order.getStatus());
        if (order == null) {
            log.warn("orderNo:{} not exist", orderNo);
            return;
        }
        CourseOrderStatusEnum statusEnum = CourseOrderStatusEnum.getByType(order.getStatus());
        switch (statusEnum) {
            case PAY_SUCCESS:
                log.warn("orderNo:{} has pay success", orderNo);
                return;
            case REFUND_APPLY:
                log.warn("orderNo:{} refund apply", orderNo);
                return;
            case REFUND_COMPLETE:
                log.warn("orderNo:{} has refund success", orderNo);
                return;
            case PAY_FIAL:
                log.warn("orderNo:{} pay fail", orderNo);
                return;
            case NOT_PAY:
                // 失效如果支付成功了，也处理
            case EXPIRED:
                // 获取兑换码
                String redeemCode = userActivityService.getRedeemCode(order.getActivityId());
                if (redeemCode == null) {
                    log.warn("orderNo:{} pay success redeemCode is empty", orderNo);
                }
                // 更新订单状态
                order.setStatus(CourseOrderStatusEnum.PAY_SUCCESS.getValue());
                order.setPayTime(LocalDateTime.now());
                order.setTransactionId(transactionId);
                order.setRedeemCode(redeemCode);
                mongoTemplate.save(order);
                log.warn("orderNo:{} pay success", orderNo);
                // 绑定兑换码
                kosCouponsService.completeByRedeemCode(order.getRedeemCode(), order.getActivityId(), order.getUserId(), order.getPhone());
                // 查询用户信息
                UserPO userPO = cacheUserService.findById(order.getUserId());
                //添加报名信息
                userPO.setSignUpVideo(Boolean.TRUE);
                userPO.setCurrentPlatform(order.getPlatform());
                userPO.setAppId(order.getAppId());
                String activityChannelId = order.getActivityChannelId();
                userPO.setActivityChannelId(activityChannelId);
                userPO.setOpenId(order.getOpenId());
                userPO.setUnionId(order.getUnionId());
                wechatMiniQaService.updateAfterSignUpUserInfo(order.getActivityId(), userPO);
                Integer sharingCommissionOrderAmount = 0;
                Integer sharingCommissionChannelOrderAmount = 0;
                //总订单金额减去分拥订单后金额
                Integer orderAmountAfter = 0;
                //分拥-个人
                UserInviteRecord userInviteRecord =
                        courseOrderCommissionServiceService.inviterDistributor(order.getUserId(),
                                order.getActivityId());
                if (Objects.nonNull(userInviteRecord) && userInviteRecord.getInviterDistributor()) {
                    DistributorApply distributorApply =
                            courseOrderCommissionServiceService.findByDistributorId(userInviteRecord.getInvitedByUserId());
                    if (Objects.nonNull(distributorApply)) {
                        SharingCommissionOrderDTO sharingCommissionOrderDto = new SharingCommissionOrderDTO();
                        sharingCommissionOrderDto.setActivityId(order.getActivityId());
                        sharingCommissionOrderDto.setAppId(order.getAppId());
                        sharingCommissionOrderDto.setMerchantId(order.getMerchantId());
                        sharingCommissionOrderDto.setDistributorCommission(distributorApply.getDistributorCommission());
                        sharingCommissionOrderDto.setMerchantName(order.getMerchantName());
                        sharingCommissionOrderDto.setOrderNo(orderNo);
                        sharingCommissionOrderDto.setPayTime(Date.from(order.getPayTime().atZone(ZoneId.systemDefault()).toInstant()));
                        sharingCommissionOrderDto.setTotalFee(order.getPrice());
                        sharingCommissionOrderDto.setTransactionId(transactionId);
                        sharingCommissionOrderDto.setCategory(SharingProfitOrderTypeEnum.KOS_ORDER.name());
                        sharingCommissionOrderAmount = courseOrderCommissionServiceService.doSharingCommissionAmount(sharingCommissionOrderDto);
                    }
                }else {
                    //渠道分拥
                    if (StringUtils.isNotBlank(activityChannelId)) {
                        DistributorChannelSharingCommissionOrderDTO sharingCommissionOrderChannelDto =
                                new DistributorChannelSharingCommissionOrderDTO();
                        sharingCommissionOrderChannelDto.setActivityId(order.getActivityId());
                        sharingCommissionOrderChannelDto.setAppId(order.getAppId());
                        sharingCommissionOrderChannelDto.setMerchantId(order.getMerchantId());
                        sharingCommissionOrderChannelDto.setMerchantName(order.getMerchantName());
                        sharingCommissionOrderChannelDto.setOrderNo(orderNo);
                        sharingCommissionOrderChannelDto.setActivityChannelId(activityChannelId);
                        sharingCommissionOrderChannelDto.setPayTime(Date.from(order.getPayTime().atZone(ZoneId.systemDefault()).toInstant()));
                        sharingCommissionOrderChannelDto.setTotalFee(order.getPrice());
                        sharingCommissionOrderChannelDto.setTransactionId(transactionId);
                        sharingCommissionOrderChannelDto.setCategory(SharingProfitOrderTypeEnum.KOS_ORDER.name());
                        sharingCommissionOrderChannelDto.setUserId(order.getUserId());
                        sharingCommissionOrderChannelDto.setMobile(order.getPhone());
                        sharingCommissionOrderChannelDto.setName(order.getName());
                        UserParticipateActivityInfo user = userParticipateActivityInfoService.findByUserIdActivityId(order.getUserId(), order.getActivityId());
                        if(Objects.nonNull(user)){
                            sharingCommissionOrderChannelDto.setUniversityId(user.getUniversityId());
                            sharingCommissionOrderChannelDto.setUniversityName(user.getUniversityName());
                        }
                        sharingCommissionChannelOrderAmount = distributorChannelSharingCommissionService.doSharingCommissionAmount(sharingCommissionOrderChannelDto);
                    }
                }
                if (sharingCommissionOrderAmount > 0 || sharingCommissionChannelOrderAmount > 0) {
                    orderAmountAfter = order.getPrice() -  Math.addExact(sharingCommissionOrderAmount, sharingCommissionChannelOrderAmount);
                } else {
                    orderAmountAfter = order.getPrice();
                }
                //分账
                OrderInfo sharingProfitOrder = new OrderInfo();
                sharingProfitOrder.setOrderNo(orderNo);
                sharingProfitOrder.setActivityId(order.getActivityId());
                sharingProfitOrder.setCategory(SharingProfitOrderTypeEnum.KOS_ORDER.name());
                sharingProfitOrder.setTotalFee(orderAmountAfter);
                sharingProfitOrder.setPayTime(Date.from(order.getPayTime().atZone(ZoneId.systemDefault()).toInstant()));
                sharingProfitOrder.setTransactionId(transactionId);
                sharingProfitOrder.setAppId(order.getAppId());
                sharingProfitOrder.setMechantId(order.getMerchantId());
                sharingProfitOrder.setMechantName(order.getMerchantName());
                merchantSharingProfitService.doSharingProfit(sharingProfitOrder);
                log.warn("UserCourseOrderService,dealOrderPaySuccess,orderNo:{} pay success", orderNo);
                return;
            default:
                break;
        }
    }


    public UserKosCouponsOrder getOrderByOrderNo(String orderNo) {
        return mongoTemplate.findOne(new Query(Criteria.where("orderNo").is(orderNo)), UserKosCouponsOrder.class);
    }

}
